package com.yang.test;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.corundumstudio.socketio.store.StoreFactory;
import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class SocketEventIOHandler {
	//服务器内部通知主题
	private RedissonClient redissonClient;
	private StoreFactory storeFactory;
	Map<String,SocketIOClient> clients = new HashMap<String, SocketIOClient>();

	private static final String ServerNode = UUID.randomUUID().toString();


	public SocketEventIOHandler(SocketIOServer server,RedissonClient redissonClient) {
		super();
		this.storeFactory = server.getConfiguration().getStoreFactory();
		this.redissonClient = redissonClient;
		this.registerServerNotifyMsgListener(redissonClient);
	}

	/**
	 * 注册兄弟服务器通知话题监听器
	 * 用于链接到其他节点上面的客户端发送消息到本节点上的客户端
	 * @param redissonClient
	 */
	private void registerServerNotifyMsgListener(RedissonClient redissonClient) {
		/**
		 * 这里订阅订阅自己的节点名称为主题，用于其他节点推送指定消息过来
		 */
		redissonClient.getTopic(ServerNode).addListener(new MessageListener<Object>() {
			public void onMessage(String topic, Object data) {
				System.out.println("收到兄弟服务器推送过来的消息：topic="+topic+",data="+data);
				String msg = (String) data;
				String[] msgData = msg.split("\\|");
				String targetUserId = msgData[0];
				String msgStr = msgData[1];

				SocketIOClient client = clients.get(targetUserId);
				if (null!=client){
					client.sendEvent("chat message",msgStr);
				}
			}
		});
	}

	@OnConnect
	public void onConnect(final SocketIOClient client){
		clients.put(client.getSessionId().toString(),client);
		storeFactory.createMap("clientServerMap").put(client.getSessionId().toString(),ServerNode);
		System.out.println("client["+client.getSessionId()+"] onConnect...");
	}
	
	@OnDisconnect
	public void onDisconnected(SocketIOClient client){
		System.out.println("client["+client.getSessionId()+"] disconnected...");
		storeFactory.createMap("clientServerMap").remove(client.getSessionId().toString());
		clients.remove(client.getSessionId().toString());
	}

	@OnEvent(value = "chat message")
	public void onEvent(SocketIOClient client,String data){
		System.out.println("client["+client.getSessionId()+"] onEvent...message:"+data);

		/**
		 * 集群p2p发送消息逻辑
		 * 1.获取消息中的目标用户和消息内容
		 * 2.检查目标用户是否链接到本节点，如果在本节点，那么直接发送消息
		 *   如果不在，那么读取全局缓存，找到用户所在的服务器节点，向该节点推送消息
		 *  （redis pub/sub实现）该节点收到消息之后，再发送给目标用户。
		 */
		String[] msgData = data.split("\\|");
		String targetUserId = msgData[0];
		String msgStr = msgData[1];

		SocketIOClient targetClient = clients.get(targetUserId);
		if (null!=targetClient){
			//目标用户在本节点
			targetClient.sendEvent("chat message",msgStr);
		}else{
			//目标用户不在本节点
			String serverNodeName = (String) storeFactory.createMap("clientServerMap").get(targetUserId);
			if (null!=serverNodeName){
				redissonClient.getTopic(serverNodeName).publish(data);
			}
		}

	}

}
